﻿using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Audio;
using Dude_Platformer.Weapon;

namespace Dude_Platformer
{
    /// <summary>
    /// Facing direction along the X axis.
    /// </summary>
    public enum FaceDirection
    {
        Left = -1,
        Right = 1,
    }

    /// <summary>
    /// An evil monster hell-bent on impeding the progress of our fearless adventurer.
    /// </summary>
    public class Enemy : Entity
    {
        private Behavior behavior;

        public Rectangle LocalBounds { get { return localBounds; } }
        private Rectangle localBounds;
        /// <summary>
        /// Gets a rectangle which bounds this enemy in world space.
        /// </summary>
        public Rectangle ThreatRectangle;
        public Rectangle FearRectangle;

        override protected void updateRectangles()
        {
            int left = (int)Math.Round(Position.X - sprite.Origin.X) + localBounds.X;
            int top = (int)Math.Round(Position.Y - sprite.Origin.Y) + localBounds.Y;

            myBoundingRectangle = new Rectangle(left, top, localBounds.Width, localBounds.Height);
            //TODO: update others rectangles
        }

        // Animations
        private Animation runAnimation;
        private Animation idleAnimation;

        // Jumping
        public void Jump()
        {
            isJumping = true;
        }

        // Sounds
        private SoundEffect killedSound;

        /// <summary>
        /// How long this enemy has been waiting before turning around.
        /// </summary>
        public float waitTime;

        /// <summary>
        /// How long to wait before turning around.
        /// </summary>
        public const float MaxWaitTime = 0.5f;
        public const float DyingTime = .8f;

        /// <summary>
        /// The speed at which this enemy moves along the X axis.
        /// </summary>
#if ZUNE
        public const float MoveSpeed = 64.0f;
        public const float MAX_VISION = 250;
#else
        public const float MoveSpeed = 128.0f;
        public const float MAX_VISION = 500;
#endif

        private Boolean isDying = false;
        public Boolean IsDying { get { return isDying; } }
        /// <summary>
        /// Constructs a new Enemy.
        /// </summary>
        public Enemy(Level level, Vector2 position, string spriteSet, GunType gunType)
            : base(level)
        {
            this.position = position;
            this.behavior = new WanderBehavior(this);

            LoadContent(spriteSet);
        }

        /// <summary>
        /// Loads a particular enemy sprite sheet and sounds.
        /// </summary>
        public void LoadContent(string spriteSet)
        {
            // Load animations.
            spriteSet = "Sprites/" + spriteSet + "/";
            runAnimation = new Animation(myLevel.Content.Load<Texture2D>(spriteSet + "Run"), 0.1f, true);
            idleAnimation = new Animation(myLevel.Content.Load<Texture2D>(spriteSet + "Idle"), 0.15f, true);
            dieAnimation = new Animation(myLevel.Content.Load<Texture2D>(spriteSet + "Die"), 0.15f, false);
            shootAnimation = new Animation(myLevel.Content.Load<Texture2D>(spriteSet + "Shoot"), 0.1f, true);
            jumpAnimation = new Animation(myLevel.Content.Load<Texture2D>(spriteSet + "Jump"), 0.1f, false);
            sprite.PlayAnimation(idleAnimation);

            // Calculate bounds within texture size.
            int width = (int)(idleAnimation.FrameWidth * 0.35);
            int left = (idleAnimation.FrameWidth - width) / 2;
            int height = (int)(idleAnimation.FrameWidth * 0.7);
            int top = idleAnimation.FrameHeight - height;
            localBounds = new Rectangle(left, top, width, height);

            // Load sounds.            
            killedSound = myLevel.Content.Load<SoundEffect>("Sounds/MonsterKilled");
        }

        /// <summary>
        /// Paces back and forth along a platform, waiting at either end.
        /// </summary>
        public void Update(GameTime gameTime)
        {
            UpdateBehavior();
            behavior.Update(gameTime);
        }

        private void UpdateBehavior()
        {
            if ((Level.Player.Position.Y == Position.Y) && (Math.Abs(Level.Player.Position.X - position.X) < MAX_VISION))
            {
                if (this.behavior.GetType() != typeof(ChaseBehavior))
                {
                    this.behavior = new ChaseBehavior(this, Level.Player);
                }
            }
            else
            {
                if (this.behavior.GetType() != typeof(WanderBehavior))
                {
                    this.behavior = new WanderBehavior(this);
                }
            }
        }

        /// <summary>
        /// Draws the animated enemy.
        /// </summary>
        public void Draw(GameTime gameTime, SpriteBatch spriteBatch)
        {
            // Stop running when the game is paused or before turning around.
            if (!myLevel.Player.IsAlive ||
                myLevel.ReachedExit ||
                waitTime > 0)
            {
                if (isDying)
                {
                    sprite.PlayAnimation(dieAnimation);
                }
                else
                {
                    sprite.PlayAnimation(idleAnimation);
                }
            }
            else
            {
                if (isDying)
                {
                    myLevel.RemoveEnnemy.Add(this);
                }
                else if (isShooting)
                {
                    sprite.PlayAnimation(shootAnimation);
                }
                else
                {
                    sprite.PlayAnimation(runAnimation);
                }
            }

            // Draw facing the way the enemy is moving.
            SpriteEffects flip = Direction > 0 ? SpriteEffects.FlipHorizontally : SpriteEffects.None;
            sprite.Draw(gameTime, spriteBatch, Position, flip);
        }

        internal void touch(Dude_Platformer.Weapon.Ammo ammo)
        {
            if (!ammo.explode)
            {
                hp -= ammo.Damage;
                ammo.explode = true;
                if ((!isDying) && (hp <= 0))
                {
                    killedSound.Play();
                    isDying = true;
                    waitTime = DyingTime;
                }
            }
        }

        protected override GunType getDefaultGunType()
        {
            return GunType.ENNEMY_GUN;
        }

        protected override int getBasicHp()
        {
            return 5;
        }
    }
}
